package org.tigris.atlas.examples.service;
 
import java.sql.Date;

import junit.framework.TestCase;

import org.tigris.atlas.examples.service.delegate.EntityMaintenanceServiceDelegate;
import org.tigris.atlas.examples.service.delegate.ServiceDelegateFactory;
import org.tigris.atlas.examples.transfer.EntityMaintenanceExample;
import org.tigris.atlas.examples.transfer.EntityMaintenanceExamplePK;
import org.tigris.atlas.examples.transfer.OneToManyChild;
import org.tigris.atlas.examples.transfer.OneToManyParent;
import org.tigris.atlas.examples.transfer.OneToManyParentPK;
import org.tigris.atlas.examples.transfer.TransferObjectFactory;
import org.tigris.atlas.examples.transfer.ValidationExample;
import org.tigris.atlas.examples.transfer.ValidationExampleChild;
import org.tigris.atlas.examples.transfer.ValidationExamplePK;

public class TestEntityMaintenanceService extends TestCase {

	private EntityMaintenanceExamplePK pk;
	private EntityMaintenanceServiceDelegate delegate;
	private int version = 1;
	
	String eme1id;
	String eme2id;
	String otmpid;
	String veid;

	protected void setUp() throws Exception {
		super.setUp();
		delegate = (EntityMaintenanceServiceDelegate) ServiceDelegateFactory.createEntityMaintenanceServiceDelegate();
		pk = (EntityMaintenanceExamplePK) TransferObjectFactory.createEntityMaintenanceExamplePK();
		
		EntityMaintenanceExample eme1 = TransferObjectFactory.createEntityMaintenanceExample();
		eme1.setName( "foo" );
		eme1.setType( "A" );
		eme1.setTheDate1( new Date( System.currentTimeMillis() ) );
		eme1 = delegate.save( eme1 ).getEntityMaintenanceExample();
		eme1id = eme1.getId();

		EntityMaintenanceExample eme2 = TransferObjectFactory.createEntityMaintenanceExample();
		eme2.setName( "bar" );
		eme2.setType( "A" );
		eme2.setTheDate1( new Date( System.currentTimeMillis() ) );
		eme2 = delegate.save( eme2 ).getEntityMaintenanceExample();
		eme2id = eme2.getId();
		
					
		OneToManyParent otmp = TransferObjectFactory.createOneToManyParent();
		otmp.setStringExample( "foo" );
		OneToManyChild otmc = TransferObjectFactory.createOneToManyChild();
		otmc.setStringExample( "bar" );
		otmp.addOneToManyChild( otmc );
		otmp = delegate.save( otmp ).getOneToManyParent();
		otmpid = otmp.getId();
		
		ValidationExample ve = TransferObjectFactory.createValidationExample();
		ve.setRequiredField( "parentFoo" );
		ValidationExampleChild vec = TransferObjectFactory.createValidationExampleChild();
		vec.setRequiredField( "childFoo" );
		ve.addValidationExampleChild( vec );
		ve = delegate.save( ve ).getValidationExample();
		veid = ve.getId();
		
	}

	protected void tearDown() throws Exception {
		EntityMaintenanceExamplePK emepk = TransferObjectFactory.createEntityMaintenanceExamplePK();
		if( eme1id != null ) {
			emepk.setId( eme1id );
			delegate.delete( emepk );
		}

		emepk.setId( eme2id );
		delegate.delete( emepk );
		
		OneToManyParentPK otmppk = TransferObjectFactory.createOneToManyParentPK();
		otmppk.setId( otmpid );
		delegate.delete( otmppk );
		
		ValidationExamplePK vepk = TransferObjectFactory.createValidationExamplePK();
		vepk.setId( veid );
		delegate.delete( vepk );
		
		super.tearDown();
	}
	
	public void testFindByPrimaryKeyRecordExists() throws Exception {
		pk.setId(eme2id);
		EntityMaintenanceExampleServiceResponse response = delegate.findByPrimaryKey(pk);
		EntityMaintenanceExample example = response.getEntityMaintenanceExample();
		
		assertNotNull(example);
		assertEquals(eme2id, example.getId());
		assertEquals("bar", example.getName());
		assertEquals("A", example.getType());
		assertNotNull(example.getTheDate1());
	}
	
	public void testFindByPrimaryKeyRecordDoesNotExist() throws Exception {
		pk.setId("316");
		EntityMaintenanceExampleServiceResponse response = delegate.findByPrimaryKey(pk);
		EntityMaintenanceExample example = response.getEntityMaintenanceExample();
		
		assertNull(example);
	}
	
	public void testCreateSuccess() throws Exception {
		Date date = new Date(System.currentTimeMillis());
		
		EntityMaintenanceExample example = (EntityMaintenanceExample) TransferObjectFactory.createEntityMaintenanceExample();
		example.setName("name");
		example.setType("C");
		example.setTheDate1(date);
		
		EntityMaintenanceExampleServiceResponse response =  delegate.save(example);
		example = response.getEntityMaintenanceExample();
		
		assertNotNull(example);
		assertFalse(example.getMessages().hasErrorMessages());
		String id = example.getId();
		assertNotNull(id);
		assertEquals("name", example.getName());
		assertEquals("C", example.getType());
		
		pk.setId(id);
		response = delegate.findByPrimaryKey(pk);
		example = response.getEntityMaintenanceExample();
		assertNotNull(example);
		assertFalse(example.getMessages().hasErrorMessages());
		assertEquals(id, example.getId());
		assertEquals("name", example.getName());
		assertEquals("C", example.getType());
	}
	
	public void testCreateFailure() throws Exception {
		EntityMaintenanceExample example = (EntityMaintenanceExample) TransferObjectFactory.createEntityMaintenanceExample();
		EntityMaintenanceExampleServiceResponse response = delegate.save(example);
		example = response.getEntityMaintenanceExample();
		assertNotNull(example);
		assertTrue(example.getMessages().hasErrorMessages());
		assertNull(example.getId());
		assertEquals(2, example.getMessages().getErrorMessageCount());
	}
	
	public void testUpdateSuccess() throws Exception {
		pk.setId(eme1id);
		EntityMaintenanceExampleServiceResponse response =  delegate.findByPrimaryKey(pk);
		EntityMaintenanceExample example = response.getEntityMaintenanceExample();
		assertNotNull(example);
		assertEquals(eme1id, example.getId());
		assertEquals("foo", example.getName());
		assertEquals("A", example.getType());
		assertNotNull(example.getTheDate1());
		
		example.setName("NewName");
		example.setType("X");
		example.setTheDate1(new Date(System.currentTimeMillis()));
		response = delegate.save(example);
		example = response.getEntityMaintenanceExample();
		assertNotNull(example);
		assertFalse(example.getMessages().hasErrorMessages());
		assertEquals(eme1id, example.getId());
		assertEquals("NewName", example.getName());
		assertEquals("X", example.getType());
		assertNotNull(example.getTheDate1());
		
		response = delegate.findByPrimaryKey(pk);
		example = response.getEntityMaintenanceExample();
		assertNotNull(example);
		assertEquals(eme1id, example.getId());
		assertEquals("NewName", example.getName());
		assertEquals("X", example.getType());
		assertNotNull(example.getTheDate1());
	}
	
	public void testUpdateFailure() throws Exception {
		pk.setId(eme1id);
		EntityMaintenanceExampleServiceResponse response = delegate.findByPrimaryKey(pk);
		EntityMaintenanceExample example = response.getEntityMaintenanceExample();
		assertNotNull(example);
		assertEquals(eme1id, example.getId());
		assertEquals("foo", example.getName());
		assertEquals("A", example.getType());
		assertNotNull(example.getTheDate1());
		
		example.setName("NewName");
		example.setType("X");
		example.setTheDate1(null);
		response = delegate.save(example);
		example = response.getEntityMaintenanceExample();
		assertNotNull(example);
		assertTrue(example.getMessages().hasErrorMessages());
		assertEquals(1, example.getMessages().getErrorMessageCount());
		assertEquals(eme1id, example.getId());
		assertEquals("NewName", example.getName());
		assertEquals("X", example.getType());
		assertNull(example.getTheDate1());
	}
	
	public void testDeleteRecordExists() throws Exception {
		pk.setId(eme1id);
		
		EntityMaintenanceExampleServiceResponse response = delegate.findByPrimaryKey(pk);
		EntityMaintenanceExample example = response.getEntityMaintenanceExample();
		assertNotNull(example);
		
		delegate.delete(((EntityMaintenanceExamplePK)example.getKey()));
		eme1id = null;
		
		response = delegate.findByPrimaryKey(pk);
		EntityMaintenanceExample afterDeleteValue = response.getEntityMaintenanceExample();
		assertNull("his record should have been deleted", afterDeleteValue);
	}
	
	public void testDeleteRecordDoesNotExist() throws Exception {
		pk.setId("213");
		
		EntityMaintenanceExampleServiceResponse response = delegate.findByPrimaryKey(pk);
		EntityMaintenanceExample example = response.getEntityMaintenanceExample();
		assertNull(example);
		
		try {
			delegate.delete(((EntityMaintenanceExamplePK)example.getKey()));
			fail("Delete should have raised an exception");
		} catch (Exception ex) {
			assertTrue(true);
		}
	}
	
	public void testDeleteChildFromParent() {
		OneToManyParentPK pk1 = TransferObjectFactory.createOneToManyParentPK();
		pk1.setId(otmpid);
		
		EntityMaintenanceServiceDelegate delegate = ServiceDelegateFactory.createEntityMaintenanceServiceDelegate();
		OneToManyParentServiceResponse response = delegate.findByPrimaryKey(pk1);
		assertNotNull(response);
		OneToManyParent parent = response.getOneToManyParent();
		
		assertEquals(1, parent.getOneToManyChilds().size());
		parent.removeOneToManyChild((OneToManyChild) parent.getOneToManyChilds().iterator().next());
		assertEquals(0, parent.getOneToManyChilds().size());
		
		parent.setStringExample("foobar");
		response = delegate.save(parent);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		parent = response.getOneToManyParent();
		assertEquals(otmpid, parent.getId());
		assertFalse(parent.getMessages().hasErrorMessages());
		assertEquals(0, parent.getOneToManyChilds().size());
		
		OneToManyParentPK pk2 = TransferObjectFactory.createOneToManyParentPK();
		pk2.setId(otmpid);
		response = delegate.findByPrimaryKey(pk2);
		assertNotNull(response);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		OneToManyParent reselect = response.getOneToManyParent();
		assertEquals("foobar", reselect.getStringExample());
		assertEquals(0, reselect.getOneToManyChilds().size());
	}
	
	public void testAddWithParentErrors() {
		ValidationExample parent = TransferObjectFactory.createValidationExample();
		
		ValidationExampleChild child = TransferObjectFactory.createValidationExampleChild();
		child.setRequiredField("foo");
		parent.addValidationExampleChild(child);
		
		EntityMaintenanceServiceDelegate delegate = ServiceDelegateFactory.createEntityMaintenanceServiceDelegate();
		ValidationExampleServiceResponse response = delegate.save(parent);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		parent = response.getValidationExample();
		child = (ValidationExampleChild) parent.getValidationExampleChilds().iterator().next();
		assertNull(parent.getId());
		assertTrue(parent.getMessages().hasErrorMessages());
		assertFalse(child.getMessages().hasErrorMessages());
		assertEquals(1, parent.getMessages().getErrorMessageCount());
		assertEquals(0, child.getMessages().getErrorMessageCount());
	}
	
	public void testAddWithChildErrors() {
		ValidationExample parent = TransferObjectFactory.createValidationExample();
		parent.setRequiredField("foo");
		
		ValidationExampleChild child = TransferObjectFactory.createValidationExampleChild();
		parent.addValidationExampleChild(child);
		
		EntityMaintenanceServiceDelegate delegate = ServiceDelegateFactory.createEntityMaintenanceServiceDelegate();
		ValidationExampleServiceResponse response = delegate.save(parent);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		parent = response.getValidationExample();
		child = (ValidationExampleChild) parent.getValidationExampleChilds().iterator().next();
		assertNull(parent.getId());
		assertFalse(parent.getMessages().hasErrorMessages());
		assertTrue(parent.getAllMessages().hasErrorMessages());
		assertTrue(child.getMessages().hasErrorMessages());
		assertTrue(child.getAllMessages().hasErrorMessages());
		assertEquals(0, parent.getMessages().getErrorMessageCount());
		assertEquals(1, parent.getAllMessages().getErrorMessageCount());
		assertEquals(1, child.getMessages().getErrorMessageCount());
		assertEquals(1, child.getAllMessages().getErrorMessageCount());
	}
	
	public void testAddWithChildAndParentErrors() {
		ValidationExample parent = TransferObjectFactory.createValidationExample();
		
		ValidationExampleChild child = TransferObjectFactory.createValidationExampleChild();
		parent.addValidationExampleChild(child);
		
		EntityMaintenanceServiceDelegate delegate = ServiceDelegateFactory.createEntityMaintenanceServiceDelegate();
		ValidationExampleServiceResponse response = delegate.save(parent);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		parent = response.getValidationExample();
		child = (ValidationExampleChild) parent.getValidationExampleChilds().iterator().next();
		assertNull(parent.getId());
		assertTrue(parent.getMessages().hasErrorMessages());
		assertTrue(child.getMessages().hasErrorMessages());
		assertEquals(1, parent.getMessages().getErrorMessageCount());
		assertEquals(1, child.getMessages().getErrorMessageCount());
	}
	
	public void testUpdateWithParentErrors() {
		ValidationExamplePK pk = TransferObjectFactory.createValidationExamplePK();
		pk.setId(veid);
		
		ValidationExampleServiceResponse response = delegate.findByPrimaryKey(pk);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		
		ValidationExample ex = response.getValidationExample();
		assertEquals("parentFoo", ex.getRequiredField());
		
		ValidationExampleChild child = (ValidationExampleChild) ex.getValidationExampleChilds().iterator().next();
		assertEquals("childFoo", child.getRequiredField());
		
		ex.setRequiredField(null);
		ex.setStringExample("foo");
		child.setRequiredField("newChildFoo");
		
		response = delegate.save(ex);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		assertTrue(response.getValidationExample().getMessages().hasErrorMessages());

		response = delegate.findByPrimaryKey(pk);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		ValidationExample reselect = response.getValidationExample();
		ValidationExampleChild reselectChild = (ValidationExampleChild) reselect.getValidationExampleChilds().iterator().next();
		assertEquals("parentFoo", reselect.getRequiredField());
		assertNull(reselect.getStringExample());
		assertEquals("childFoo", reselectChild.getRequiredField());
	}
	
	public void testUpdateWithChildErrors() {
		ValidationExamplePK pk = TransferObjectFactory.createValidationExamplePK();
		pk.setId(veid);
		
		ValidationExampleServiceResponse response = delegate.findByPrimaryKey(pk);
		
		ValidationExample ex = response.getValidationExample();
		assertEquals("parentFoo", ex.getRequiredField());
		
		ValidationExampleChild child = (ValidationExampleChild) ex.getValidationExampleChilds().iterator().next();
		assertEquals("childFoo", child.getRequiredField());
		
		ex.setRequiredField("newParentFoo");
		ex.setStringExample("foo");
		child.setRequiredField(null);
		
		response = delegate.save(ex);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		assertFalse(response.getValidationExample().getMessages().hasErrorMessages());
		assertTrue(response.getValidationExample().getAllMessages().hasErrorMessages());

		response = delegate.findByPrimaryKey(pk);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		ValidationExample reselect = response.getValidationExample();
		ValidationExampleChild reselectChild = (ValidationExampleChild) reselect.getValidationExampleChilds().iterator().next();
		assertEquals("parentFoo", reselect.getRequiredField());
		assertNull(reselect.getStringExample());
		assertEquals("childFoo", reselectChild.getRequiredField());
	}
	
	public void testUpdateWithNoErrors() {
		ValidationExamplePK pk = TransferObjectFactory.createValidationExamplePK();
		pk.setId(veid);
		
		ValidationExampleServiceResponse response = delegate.findByPrimaryKey(pk);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		
		ValidationExample ex = response.getValidationExample();
		assertEquals("parentFoo", ex.getRequiredField());
		
		ValidationExampleChild child = (ValidationExampleChild) ex.getValidationExampleChilds().iterator().next();
		assertEquals("childFoo", child.getRequiredField());
		
		ex.setRequiredField("newParentFoo");
		ex.setStringExample("foo");
		child.setRequiredField("newChildFoo");
		assertNotNull(child.getRequiredField());
		
		response = delegate.save(ex);
		ValidationExample reselect = response.getValidationExample();
		ValidationExampleChild reselectChild = (ValidationExampleChild) reselect.getValidationExampleChilds().iterator().next();
		assertEquals(0, response.getMessages().getErrorMessageCount());
		assertFalse(response.getValidationExample().getMessages().hasErrorMessages());

		response = delegate.findByPrimaryKey(pk);
		assertEquals("newParentFoo", reselect.getRequiredField());
		assertEquals("foo", reselect.getStringExample());
		assertEquals("newChildFoo", reselectChild.getRequiredField());
	}
	
	public void testUpdateWithParentAndChildErrors() {
		ValidationExamplePK pk = TransferObjectFactory.createValidationExamplePK();
		pk.setId(veid);
		
		ValidationExampleServiceResponse response = delegate.findByPrimaryKey(pk);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		
		ValidationExample ex = response.getValidationExample();
		assertEquals("parentFoo", ex.getRequiredField());
		
		ValidationExampleChild child = (ValidationExampleChild) ex.getValidationExampleChilds().iterator().next();
		assertEquals("childFoo", child.getRequiredField());
		
		ex.setRequiredField(null);
		ex.setStringExample("foo");
		child.setRequiredField(null);
		
		response = delegate.save(ex);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		assertTrue(response.getValidationExample().getMessages().hasErrorMessages());

		response = delegate.findByPrimaryKey(pk);
		assertEquals(0, response.getMessages().getErrorMessageCount());
		ValidationExample reselect = response.getValidationExample();
		ValidationExampleChild reselectChild = (ValidationExampleChild) reselect.getValidationExampleChilds().iterator().next();
		assertEquals("parentFoo", reselect.getRequiredField());
		assertNull(reselect.getStringExample());
		assertEquals("childFoo", reselectChild.getRequiredField());
	}
	
	public void testRemoveUnsavedChild() {
		EntityMaintenanceServiceDelegate emDelegate = ServiceDelegateFactory.createEntityMaintenanceServiceDelegate();
		ValidationExample parent = TransferObjectFactory.createValidationExample();
		parent.setRequiredField("foo");
		
		ValidationExampleChild item1 = TransferObjectFactory.createValidationExampleChild();
		item1.setRequiredField(null);
		
		ValidationExampleChild item2 = TransferObjectFactory.createValidationExampleChild();
		item2.setRequiredField("item2");
		
		assertFalse("These 2 instances should not be equal!", item1.equals(item2));
		
		parent.addValidationExampleChild(item1);
		
		ValidationExampleServiceResponse response = emDelegate.save(parent);
		ValidationExample savedJournal = response.getValidationExample();
		assertFalse(savedJournal.getMessages().hasErrorMessages());
		assertTrue(savedJournal.getAllMessages().hasErrorMessages());
		
		ValidationExampleChild unsavedItem = (ValidationExampleChild) savedJournal.getValidationExampleChilds().iterator().next();
		assertTrue(unsavedItem.equals(unsavedItem));
		assertFalse(unsavedItem.equals(item1));
		
		assertTrue(savedJournal.getValidationExampleChilds().contains(unsavedItem));

        assertEquals(1, savedJournal.getValidationExampleChilds().size());
		savedJournal.removeValidationExampleChild(unsavedItem);
        assertEquals(0, savedJournal.getValidationExampleChilds().size());
	}
	
}
